package com.yindian.cos.easy.security.authentication.verify;

import com.yindian.cos.easy.security.exception.AuthenticationException;
import com.yindian.cos.easy.security.properties.EasySecurityProperties;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 根据系统配置选择是否放行
 *
 * @author zhangchuanhao
 * @create 2018/11/23
 */
@Log4j2
public class SystemPathVerifyAuthentication extends AbstractVerifyAuthentication {

    /**
     * 根据配置项挑选出对应的url放入此map
     * key为url，value为是否继续向下执行
     */
    private static final Map<String, Boolean> urls = new ConcurrentHashMap<>();

    /**
     * 获取系统自动放行的路径，已供自定义之后进行设置
     *
     * @return
     */
    public static Map<String, Boolean> getUrls() {
        return urls;
    }

    private AtomicBoolean next = new AtomicBoolean(true);

    public SystemPathVerifyAuthentication(EasySecurityProperties easySecurityProperties) {
        // 第三方用户第一次登录时应该引导用户跳转的注册地址
        String registerUrl = easySecurityProperties.getRegisterUrl();
        if (StringUtils.isNotBlank(registerUrl)) {
            if (!StringUtils.startsWith(registerUrl, "http")) {
                urls.put(registerUrl, false);
            }
        }

        // 表单登录地址
        boolean formLoginEnable = easySecurityProperties.getForm().getEnable();
        String formLoginUrl = easySecurityProperties.getForm().getLoginUrl();
        addUrl(formLoginEnable, formLoginUrl, urls, true);

        // 短信验证码登录地址
        boolean smsCodeLoginEnable = easySecurityProperties.getSmsCode().getEnable();
        String smsCodeLoginUrl = easySecurityProperties.getSmsCode().getLoginUrl();
        addUrl(smsCodeLoginEnable, smsCodeLoginUrl, urls, true);

        // qq登录地址
        boolean qqLoginEnable = easySecurityProperties.getQq().getEnable();
        String qqLoginUrl = easySecurityProperties.getQq().getLoginUrl();
        String qqRedirectUri = easySecurityProperties.getQq().getRedirectUri();
        addUrl(qqLoginEnable, qqLoginUrl, urls, true);
        addUrl(qqLoginEnable, qqRedirectUri, urls, false);

        // 微博登录地址
        boolean weiBoLoginEnable = easySecurityProperties.getWeibo().getEnable();
        String weiBoLoginUrl = easySecurityProperties.getWeibo().getLoginUrl();
        String weiBoRedirectUri = easySecurityProperties.getWeibo().getRedirectUri();
        addUrl(weiBoLoginEnable, weiBoLoginUrl, urls, true);
        addUrl(weiBoLoginEnable, weiBoRedirectUri, urls, false);

        // 微信登录地址
        boolean weiXinLoginEnable = easySecurityProperties.getWeixin().getEnable();
        String weiXinLoginUrl = easySecurityProperties.getWeixin().getLoginUrl();
        String weiXinRedirectUri = easySecurityProperties.getWeixin().getRedirectUri();
        addUrl(weiXinLoginEnable, weiXinLoginUrl, urls, true);
        addUrl(weiXinLoginEnable, weiXinRedirectUri, urls, false);

        // 退出地址
        boolean logoutEnable = easySecurityProperties.getLogout().getEnable();
        String logoutUrl = easySecurityProperties.getLogout().getLogoutUrl();
        addUrl(logoutEnable, logoutUrl, urls, true);

        // 第三方登录注册回调
        if (qqLoginEnable || weiBoLoginEnable || weiXinLoginEnable) {
            urls.put("/social/register/notify", false);
        }

        // 刷新token
        urls.put("/token/refresh", false);

        log.debug("系统默认放行地址，urls = {}", urls);
    }

    /**
     * 判断是否添加url
     *
     * @param enable 是否添加
     * @param url    请求地址
     * @param urls   请求地址集合
     * @param next   是否继续向下执行
     */
    public void addUrl(boolean enable, String url, Map<String, Boolean> urls, boolean next) {
        if (enable) {
            if (StringUtils.isNotBlank(url)) {
                urls.put(url.trim(), next);
            }
        }
    }

    @Override
    public void verify(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        String requestUrl = request.getRequestURI();
        if (urls.containsKey(requestUrl)) {
            next.set(urls.get(requestUrl));
        }
    }

    @Override
    public boolean next(HttpServletRequest request) {
        return next.get();
    }

    @Override
    public boolean support(HttpServletRequest request) {
        String requestUrl = request.getRequestURI();
        boolean flag = urls.containsKey(requestUrl);
        if (flag) {
            log.debug("执行拦截过滤器{}", this.getClass().getSimpleName());
        }
        return flag;
    }

    public boolean support(String url) {
        return urls.containsKey(url);
    }

    @Override
    public int order() {
        return -1000;
    }
}
